<?php
class Prov_proveedores extends MY_Controller {

	public function __construct()
    {
    	# Al constructor le envío la clase Controlador, y el nombre de la entidad gestionada
    	parent::__construct(get_class($this), 'Prov_proveedor');

    	$this->title = 'Proveedores :: Proveedores';
		$this->CARPETA_VISTAS = 'proveedores/';
		$this->nombre_entidad = 'Proveedor';
		$this->nombre_entidad_plural = 'Proveedores';

		$this->pagina_ver = $this->CARPETA_VISTAS . 'proveedor_ver_todos_view';
		$this->pagina_editar = $this->CARPETA_VISTAS . 'proveedor_edit_view';
		$this->pagina_filtros_ver = $this->CARPETA_VISTAS . 'proveedor_filtros_ver_todos_view';
	}

	/* IMPORTANTE: DEBE existir esta función. 
	 * Crea un objeto de la entidad correspondiente y lo pobla con la información obtenida a 
	 * partir del formulario recibido a través de POST.	*/
	protected function getObjetoDesdeForm()
	{
		$idEntidad = is_numeric($this->input->post('txt_id')) ? $this->input->post('txt_id') : NULL;
		
		$objEntidad = $this->getObjeto($idEntidad);
		$objEntidad->razon_social = $this->input->post('txt_razon_social');
		$objEntidad->numero_doc = $this->input->post('txt_numero_doc');
		$objEntidad->telefono = $this->input->post('txt_telefono');
		$objEntidad->telefono2 = $this->input->post('txt_telefono2');
		$objEntidad->email = $this->input->post('txt_email');
		$objEntidad->observaciones = $this->input->post('txt_observaciones');
		$objEntidad->margen_ganancia = $this->input->post('txt_margen_ganancia');
		$objEntidad->afip_tipodoc_id = $this->input->post('sel_documento');
		$objEntidad->afip_tiporesponsable_id = $this->input->post('sel_responsable');

		$fecha_actual = date($this->formatoFechaGuardar);
		if($idEntidad == 0 || $idEntidad == NULL)
			$objEntidad->fecha_alta = $fecha_actual;

		$de_baja = $this->input->post('chk_baja');
		if($objEntidad->baja != $de_baja){
			$objEntidad->baja = $de_baja ? TRUE : FALSE;
			if($de_baja) $objEntidad->fecha_baja = $fecha_actual;
		}


		// OBJETOS RELACIONADOS
		$objetosRel = array();

		$this->load->library('util_ubicacion');
		$id_ubicacion = is_numeric($this->input->post('txt_ubicacion')) ? $this->input->post('txt_ubicacion') : NULL;
		$objUbicacion = $this->util_ubicacion->cargarUbicacion($id_ubicacion, 
															   $this->input->post('f_txt_localidad_id'),
															   $this->input->post('f_txt_calle_id'),
															   $this->input->post('txt_altura'),
															   $this->input->post('txt_piso'),
															   $this->input->post('txt_depto'));	
		$objetosRel[] = $objUbicacion;

		$datos['objEntidad'] = $objEntidad;
		$datos['objRelacionados'] = $objetosRel;

		return $datos;
	}

	/* IMPORTANTE: DEBE existir esta función. 
	 * Carga en el arreglo que luego se pasarán a las vistas, los datos correspondientes a otras entidades que se
	 * necesiten. Por ejemplo, en este método deben cargarse las entidades a las que puede asociarse o relacionarse
	 * la entidad actual. Si no se requiriesen, no se agrega nada. */
	protected function cargarDatosRelacionados($dataView)
	{
		// Creo un objeto del modelo, para poder buscar todos los datos en la BD
		$obj_doc = new Afip_documento();
		$obj_doc->order_by('descripcion', 'asc');
		$dataView['listado_documentos'] = $obj_doc->get_iterated();

		$obj_resp = new Afip_responsable();
		$obj_resp->order_by('descripcion', 'asc');
		$dataView['listado_responsables'] = $obj_resp->get_iterated();

		return $dataView;
	}

	/* IMPORTANTE: DEBE existir esta función. 
	 * Obtiene el listado de elementos de acuerdo a los filtros que se hayan establecido y enviado a través
	 * del método POST. Devuelve un detalle de los filtros aplicados (o vacío si no hubiera filtros)	*/	
	protected function _aplicarFiltros($dataView = array())
	{
		// Creo un objeto del modelo, para poblarlo con los datos que necesito mostrar
		$objEntidad = $this->getObjeto();
		$detalle_filtros = '';

		$raz_soc = trim($this->input->post('f_txt_razon_social'));
		if(empty($raz_soc)) { $raz_soc = trim($this->input->post('f_txt_nombre')); }
		if(!empty($raz_soc)) { 
			$objEntidad->like('razon_social', $raz_soc); 
			$detalle_filtros .= (!empty($detalle_filtros) ? ' | ' : '') . 'Razón Social => ' . $raz_soc;
		}

		$num_doc = trim($this->input->post('f_txt_numero_doc'));
		if(!empty($num_doc)) { 
			$objEntidad->like('numero_doc', $num_doc); 
			$detalle_filtros .= (!empty($detalle_filtros) ? ' | ' : '') . 'N° Documento => ' . $num_doc;
		}

		$documento = $this->input->post('f_sel_documento');
		if($documento != 0) {
			$objEntidad->where('afip_tipodoc_id', $documento); 
			$detalle_filtros .= (!empty($detalle_filtros) ? ' | ' : '') . 'Tipo Documento ';
		}

		$responsable = $this->input->post('f_sel_responsable');
		if($responsable != 0) {
			$objEntidad->where('afip_tiporesponsable_id', $responsable); 
			$detalle_filtros .= (!empty($detalle_filtros) ? ' | ' : '') . 'Responsable ';
		}

		$dataView['objEntidad'] = $objEntidad;
		$dataView['detalle_filtros'] = $detalle_filtros;

		return $dataView;
	}

	/* Sobreescribo el método padre para guardar primero el objeto ubicación. */
	public function guardar()
	{
		/* Necesito asegurarme que la ubicación que se relacionará al proveedor esté guardada */
		$datos = $this->getObjetoDesdeForm();
		$objRelacionados = $datos['objRelacionados'];
		$objUbicacion = $objRelacionados[0];
		
		$this->load->library('util_ubicacion');
		$resultado = $this->util_ubicacion->guardar($objUbicacion);
		$objUbicacion = $resultado['objUbicacion'];
		$datos['objRelacionados'] = array($objUbicacion);

		$dataView = parent::guardarEntidad($datos);
		if(!empty($dataView['error'])) {
			// Falló el intento de guardar
			parent::_cargarFormEdicion($dataView, TRUE); 
		}
		else { parent::ver_todos($dataView); }
	}

	/* IMPORTANTE: DEBE existir esta función.
	 * Valida las condiciones que deben cumplirse para que un elemento pueda ELIMINARSE. */
	protected function validarEliminacion($id_elemento)
	{
		// Valido si tiene elementos asociados.
		$objProductos = new Prod_proveedor_producto();
        $objProductos->where('prov_proveedor_id', $id_elemento);

        if ($objProductos->count() == 0) return TRUE;
        else return FALSE;
	}

	/* IMPORTANTE: DEBE existir esta función.
	 * Valida las condiciones que deben cumplirse para que un elemento pueda EDITARSE o CREARSE NUEVO. */
	protected function validarEdicion($id_elemento)
	{
		return TRUE;
	}

	/** Llamada desde AJAX para mostrar un resumen de un objeto. Se sobreescribe el método heredado
	para darle un comportamiento particular. */
	public function toString($id_elemento, $datos = '', $objEntidad = NULL)
	{
		if($objEntidad == NULL) $objEntidad = $this->getObjeto($id_elemento);
		
		$id_elemento = $objEntidad->id;

		$datos = '<h4>Detalle del Proveedor</strong></h4>';
		$datos .= $objEntidad->toString();
		$datos .= "<input type='hidden' id ='txt_prov_id' name ='txt_prov_id' value='$id_elemento'>";

		parent::toString($id_elemento, $datos);
	}

	/** Llamada desde AJAX para mostrar un resumen de un objeto. Se sobreescribe el método heredado
	para darle un comportamiento particular. */
	public function cargarSegunFiltro($nombre, $codigo)
	{
		$objEntidad = $this->getObjeto();
		
		if($nombre != '-' || $codigo != 0) {
			if($codigo != 0) $objEntidad->where('id', $codigo);
			if($nombre != '-') $objEntidad->like('razon_social', $nombre);

			$objEntidad->limit(1);
			$objEntidad->order_by('id', 'desc');
			$objEntidad->get();
			if ($objEntidad->exists()) $this->toString($objEntidad->id, '', $objEntidad);
			else echo "<pre><p>No se encontraron coincidencias con lo ingresado</p></pre>";
		}
		else echo "<pre><p>Debe ingresar filtros de búsqueda antes de continuar</p></pre>";
	}

	public function generar_excel()
    {
        $dataView['entidad_plural'] = 'Proveedores';
        $dataView['datos_campos'] = array(array('field', 'razon_social'),
                                            array('relation', 'descripcion', 'afip_documento'), 
                                            array('field', 'numero_doc'),
                                            array('relation', 'descripcion', 'afip_responsable'),
                                            array('field', 'telefono'),
                                            array('field', 'telefono2'),
                                            array('field', 'email'),
                                            array('field', 'margen_ganancia'));
        $dataView['headers_datos'] = array('Razón Social', 'Documento', 'Número', 'Responsable', 'Teléfono', 'Otro teléfono', 'Email', '% Ganancia');

        parent::generar_excel($dataView);
    }

    /* Filtra los datos y devuelve sólo código y nombre. IMPRIME el resultado con JSON, para AJAX */
	public function busqueda_rapida()
	{
		$dataView = $this->filtrar();
		$opciones = array();
		foreach ($dataView['listado'] as $objEntidad) {	
			$opciones[$objEntidad->id] = $objEntidad->razon_social;
		}
		
		if($this->input->is_ajax_request()) {
			$json = json_encode($opciones);
			echo $json;
		}
		else return $opciones;
	}

	public function importar_lp($id_elemento){
		$dataView['objEntidad'] = $this->getObjeto($id_elemento);
		$dataView['title'] = 'Actualizar Precios a partir de una Lista';
		$dataView['pagina_editar'] = $this->CARPETA_VISTAS . 'proveedor_importar_lp_edit_view';
		$dataView['nombre_controlador'] = '';
		$dataView['metodo_guardar'] = '';
		$dataView['noMostrarTitulo'] = TRUE;
		$dataView['id_entidad'] = $id_elemento;

		// Notifico si existe alguna configuración de importación cargada para el proveedor
		 $dataView['config_cargada'] = $this->getConfiguracionImportacion($id_elemento)->exists();

		$path = strtolower($this->nombre_controlador) . "/" . 'actualizar_precios';
		$datos = "{'txt_id': $('#txt_id').val(), 'chk_tieneCabeceras': $('#chk_tieneCabeceras').val(), 'chk_usarConfig': $('#chk_usarConfig').val(), 'chk_ignorarCero': $('#chk_ignorarCero').val(), 'chk_soloActivos': $('#chk_soloActivos').val()}";
		$dataView['metodo_subir_archivo'] = "cargarArchivo('$path', 'resultado_importacion', $datos)";

		parent::_loadFileUploadView($dataView, FALSE);
	}

	private function getConfiguracionImportacion($idProveedor) {
		$objConfig = new Conf_importar_Excel();
		$objConfig->where('prov_proveedor_id', $idProveedor);
		$objConfig->get(1);

		return $objConfig;
	}

	public function actualizar_precios() {
		// Intento guardar el archivo si hubiera
		$config['upload_path'] = './documentos/temporales';
		$config['allowed_types'] = 'xls|xlsx';
		
		$this->load->library('upload', $config);
		if (!$this->upload->do_upload()) {
			echo 'Error: ' . $this->upload->display_errors();
		}
		else {
			$datos_archivo = $this->upload->data();
			$path_archivo = $datos_archivo['full_path'];
			
			$idProveedor = is_numeric($this->input->post('txt_id')) ? $this->input->post('txt_id') : NULL;
			$tieneCabeceras = $this->input->post('chk_tieneCabeceras');
			$usarConfig = $this->input->post('chk_usarConfig');
			$ignorarCeroOVacio = $this->input->post('chk_ignorarCero');
			$soloActivos = $this->input->post('chk_soloActivos');

			$this->load->library('to_excel');
			$objPHPExcel = $this->to_excel->cargarExcel($path_archivo);

			// Por defecto, si no se configura otra cosa, se consideran las 3 primeras columnas
			$col_codigo = 0;
			$col_pesos = 1;
			$col_dolares = 2;
			$filaInicio = 1;
			if($usarConfig) {
				$objConfig = $this->getConfiguracionImportacion($idProveedor);
				if($objConfig->exists() > 0) {
					// Existe configuración para el proveedor
					if(!empty($objConfig->col_codigo)) $col_codigo = PHPExcel_Cell::columnIndexFromString($objConfig->col_codigo) - 1;
					if(!empty($objConfig->col_importe_pesos)) $col_pesos = PHPExcel_Cell::columnIndexFromString($objConfig->col_importe_pesos) - 1;
					if(!empty($objConfig->col_importe_dolares)) $col_dolares = PHPExcel_Cell::columnIndexFromString($objConfig->col_importe_dolares) - 1;
					if(is_numeric($objConfig->cant_filas_cabecera)) $filaInicio += $objConfig->cant_filas_cabecera;
				}
				else { if($tieneCabeceras) $filaInicio++; }
			}
			else { if($tieneCabeceras) $filaInicio++; }

			$cantActualizaciones = 0;
			$cantProductoTotal = 0;
			$detalle_no_actualizados = "";
			// Las filas comienzan desde el índice 1. Las columnas desde 0
			$cantFilas = $objPHPExcel->getActiveSheet()->getHighestRow();
			for($fila = $filaInicio; $fila <= $cantFilas; $fila++){
				$valor_codigo = $objPHPExcel->getActiveSheet()->getCellByColumnAndRow($col_codigo,$fila)->getFormattedValue();
				$valor_pesos = $objPHPExcel->getActiveSheet()->getCellByColumnAndRow($col_pesos,$fila)->getFormattedValue();
				$valor_dolares = $objPHPExcel->getActiveSheet()->getCellByColumnAndRow($col_dolares,$fila)->getFormattedValue();

				if(!empty($valor_codigo)) { 
					if(!$ignorarCeroOVacio || ($ignorarCeroOVacio && (!empty($valor_pesos) || !empty($valor_dolares)))) {

						$objProvProd = new Prod_proveedor_producto();
						$objProvProd->where('prov_proveedor_id', $idProveedor);
						$objProvProd->where('codigo', $valor_codigo);
						if($soloActivos) $objProvProd->where_related_prod_producto('baja', FALSE);
						$objProvProd->get(1);
						if($objProvProd->exists()) {
							$cantProductoTotal++;

							// Encontró el producto según el código de producto del proveedor
							$campos_actualizar = array();
							if(!empty($valor_pesos) && is_numeric($valor_pesos)) $campos_actualizar['importe_pesos'] = $valor_pesos;
							else { if(!$ignorarCeroOVacio) $campos_actualizar['importe_pesos'] = 0; }
							
							if(!empty($valor_dolares) && is_numeric($valor_dolares)) $campos_actualizar['importe_dolares'] = $valor_dolares;
							else { if(!$ignorarCeroOVacio) $campos_actualizar['importe_dolares'] = 0; }

							$campos_actualizar['fecha_actualizacion'] = date($this->formatoFechaGuardar);
							$objProvProd->where(array('prov_proveedor_id' => $idProveedor, 'codigo' => $valor_codigo))->update($campos_actualizar);
							$filas_afectadas = $objProvProd->db->affected_rows();
							$cantActualizaciones += $filas_afectadas;

							if($filas_afectadas == 0 || !$filas_afectadas) $detalle_no_actualizados .= '</br>No se pudo actualizar: ' . $valor_codigo;
						}
						else $detalle_no_actualizados .= '<br/>Producto no encontrado o dado de baja. Código: ' . $valor_codigo;
					}
				}
			}

			echo "<div class='box_busqueda' style='height:300px; overflow: auto'>Proceso completo. De un total de $cantProductoTotal posibles actualizaciones, se realizaron $cantActualizaciones correctas.";
			if (!empty($detalle_no_actualizados)) echo "<br/><br/>DETALLE DE PRODUCTOS NO ACTUALIZADOS$detalle_no_actualizados";
			echo "<div>";

			# Elimino el archivo de prueba utilizado
			if (file_exists($path_archivo)){
				unlink($path_archivo);
			}
		}
	}
}